package com.video.mall.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.map.MapUtil;
import cn.hutool.json.JSON;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.toolkit.Db;
import com.video.common.domain.QueryPageDto;
import com.video.common.enumeration.AppHttpCodeEnum;
import com.video.common.result.PageResult;
import com.video.common.result.ResponseResult;
import com.video.mall.domain.dto.ProductDto;
import com.video.mall.domain.entity.Product;
import com.video.mall.domain.entity.ProductSwipe;
import com.video.mall.domain.entity.Standard;
import com.video.mall.mapper.ProductMapper;
import com.video.mall.service.IProductService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.RequiredArgsConstructor;
import org.elasticsearch.action.admin.indices.refresh.RefreshRequest;
import org.elasticsearch.action.search.SearchRequest;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.action.update.UpdateRequest;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.common.xcontent.XContentType;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.SearchHit;
import org.elasticsearch.search.builder.SearchSourceBuilder;
import org.elasticsearch.search.sort.SortOrder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * <p>
 * 商品表 服务实现类
 * </p>
 *
 * @author la
 * @since 2024-11-19
 */
@Service
public class ProductServiceImpl extends ServiceImpl<ProductMapper, Product> implements IProductService {

    /*
     * 分页查询商品
     * */
    @Override
    public PageResult queryList(QueryPageDto dto, RestHighLevelClient client) throws IOException {
        // 校验数据
        dto.validateParams();

        // 构建Es查询请求
        SearchRequest searchRequest = new SearchRequest("product");
        SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();

        // 设置分页
        searchSourceBuilder.from((dto.getPage() - 1) * dto.getPageSize());
        searchSourceBuilder.size(dto.getPageSize());

        // 设置排序
        searchSourceBuilder.sort("createTime", SortOrder.DESC);

        // 构建查询条件
        BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();
        if (dto.getKeywords() != null && !dto.getKeywords().isEmpty()) {
            boolQueryBuilder.must(QueryBuilders.matchQuery("title", dto.getKeywords()));
        }
        searchSourceBuilder.query(boolQueryBuilder);
        searchRequest.source(searchSourceBuilder);
        SearchResponse response = client.search(searchRequest, RequestOptions.DEFAULT);

        // 转换数据
        List<ProductDto> productDtos = new ArrayList<>();

        for (SearchHit hit : response.getHits()) {
            ProductDto productDto = BeanUtil.copyProperties(hit.getSourceAsMap(), ProductDto.class);
            System.out.println("数据源-----------------" + productDto);
            productDtos.add(productDto);
        }

        productDtos.forEach(item -> {
            List<ProductSwipe> swipeList = Db.lambdaQuery(ProductSwipe.class)
                    .eq(ProductSwipe::getProductId, item.getId())
                    .list();
            List<Standard> standards = Db.lambdaQuery(Standard.class)
                    .eq(Standard::getProductId, item.getId())
                    .list();
            item.setStandardList(standards);
            item.setSwipeList(swipeList);
        });

        System.out.println("数据源-----------------" + productDtos);


        return new PageResult(response.getHits().getTotalHits().value, productDtos);
    }

    /*
     * 添加或编辑商品信息
     * */
    @Override
    @Transactional
    public ResponseResult saveOrUpdateProduct(ProductDto productDto, RestHighLevelClient client) throws IOException {
        // 拷贝属性
        Product product = BeanUtil.copyProperties(productDto, Product.class);
        product.setUpdateTime(System.currentTimeMillis());
        // 判断新增或编辑状态
        if (product.getId() == null) {
            // 设置时间
            product.setCreateTime(System.currentTimeMillis());
            product.setSales(0);
            product.setCollectSize(0);

            // 保存到数据库并返回id
            boolean saved = save(product);
            // 判断是否保存成功
            if (saved) {
                Long productId = product.getId();
                // 保存数据到 商品轮播图表
                List<ProductSwipe> swipeList = productDto.getSwipeList();
                List<Standard> standardList = productDto.getStandardList();
                swipeList.forEach(item -> {
                    item.setProductId(productId);
                });
                standardList.forEach(item -> {
                    item.setProductId(productId);
                });
                Db.saveBatch(swipeList);
                Db.saveBatch(standardList);

            } else {
                return ResponseResult.errorResult(633, "保存失败");
            }
        } else {
            // 删除商品下属轮播
            List<ProductSwipe> list = Db.lambdaQuery(ProductSwipe.class)
                    .eq(ProductSwipe::getProductId, product.getId())
                    .list();

            // 删除规格下属信息
            List<Standard> standards = Db.lambdaQuery(Standard.class)
                    .eq(Standard::getProductId, product.getId())
                    .list();
            List<Long> swipeIds = list.stream().map(ProductSwipe::getId).collect(Collectors.toList());
            List<Long> standardIds = standards.stream().map(Standard::getId).collect(Collectors.toList());

            if (CollUtil.isNotEmpty(swipeIds)) {
                Db.removeByIds(swipeIds, ProductSwipe.class);
            }

            if (CollUtil.isNotEmpty(standardIds)) {
                Db.removeByIds(standardIds, Standard.class);
            }

            // 保存新的轮播数据到数据库
            List<ProductSwipe> swipeList = productDto.getSwipeList();
            List<Standard> standardList = productDto.getStandardList();
            swipeList.forEach(item -> {
                item.setProductId(productDto.getId());
            });
            standardList.forEach(item -> {
                item.setProductId(productDto.getId());
            });
            Db.saveBatch(swipeList);
            Db.saveBatch(standardList);
            updateById(product);
        }

        Map<String, Object> productMap = BeanUtil.beanToMap(product);

        System.out.println("productMap-----------------" + productMap);
        // 保存数据到es
        UpdateRequest request = new UpdateRequest("product", product.getId().toString());
        // 上传源
        request
                .doc(productMap) // 上传源
                .upsert(productMap); // 没有就新增
        // 更新数据
        client.update(request, RequestOptions.DEFAULT);
        // 在更新数据后，手动刷新索引以确保数据立即可见：
        client.indices().refresh(new RefreshRequest("product"), RequestOptions.DEFAULT);

        return ResponseResult.okResult(AppHttpCodeEnum.SUCCESS);
    }
}
